use crate::ast::*;
use crate::error::Result;

use super::LLVMBackend;

impl<'ctx> LLVMBackend<'ctx> {
    pub(super) fn enter_scope(&mut self) {
        self.scope_stack.push(Vec::new());
    }

    /// Exit current scope and execute all defer statements in LIFO order
    pub(super) fn exit_scope(&mut self) -> Result<()> {
        if let Some(defer_stack) = self.scope_stack.pop() {
            // Execute all defer statements in reverse order (LIFO)
            for expr in defer_stack.into_iter().rev() {
                let _ = self.generate_expression(&expr)?;
            }
        }
        Ok(())
    }

    /// Add a defer statement to the current scope
    pub(super) fn add_defer_to_current_scope(&mut self, expr: Expression) {
        if let Some(current_scope) = self.scope_stack.last_mut() {
            current_scope.push(expr);
        } else {
            // If no scope exists, create a new one
            self.scope_stack.push(vec![expr]);
        }
    }

    /// Execute all defer statements in all scopes (for function cleanup)
    pub(super) fn execute_all_defer_statements(&mut self) -> Result<()> {
        // Execute all scopes in reverse order (LIFO)
        while let Some(defer_stack) = self.scope_stack.pop() {
            for expr in defer_stack.into_iter().rev() {
                let _ = self.generate_expression(&expr)?;
            }
        }
        Ok(())
    }
}
